package org.bot.server.flow.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.bot.client.driver.api.client.ClientOpenApi;
import org.bot.server.client.entity.BotClient;
import org.bot.server.flow.entity.BotFlow;
import org.bot.server.flow.mapper.BotFlowMapper;
import org.bot.server.flow.service.BotFlowService;
import org.bot.server.job.FlowQuartzJob;
import org.bot.server.utils.AESUtils;
import org.bot.server.utils.ServletUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author 沧月
 * @create 0021 2023/9/21 14:04
 * @description <description class purpose>
 */
@Service
public class BotFlowServiceImpl implements BotFlowService {

    @Autowired
    BotFlowMapper flowMapper;

    @Autowired
    ClientOpenApi clientFlowExecute;

    @Autowired
    FlowQuartzJob quartzJob;

    @Override
    public List<Map<String, Object>> list(String name, Integer clientId, Integer page, Integer size) {
        return flowMapper.list(name, clientId,(page - 1) * size, size);
    }

    @Override
    public Integer listCount(String name) {
        return flowMapper.listCount(name);
    }

    @Override
    public boolean delete(Integer id) {
        quartzJob.deleteFlowJob(id.toString());
        return flowMapper.deleteById(id) > 0;
    }

    @Override
    public boolean save(BotFlow botFlow) {
        botFlow.setStatus(1);
        boolean stat = flowMapper.insert(botFlow) > 0;

        //添加自动任务
        if (stat && 2 == botFlow.getFlowType()) {
            quartzJob.addFlowJob(botFlow.getId().toString());
        }
        return stat;
    }

    @Override
    public boolean edit(BotFlow botFlow) {
        boolean stat = flowMapper.updateById(botFlow) > 0;
        if (stat) {
            quartzJob.deleteFlowJob(botFlow.getId().toString());
            if (botFlow.getFlowType() == 2) {
                quartzJob.addFlowJob(botFlow.getId().toString());
            }
        }
        return flowMapper.updateById(botFlow) > 0;
    }

    @Override
    public boolean updateFlowInfo(Integer id, String x6JSON, String botJSON) {
        BotFlow botFlow = new BotFlow();
        botFlow.setId(id);
        botFlow.setX6JSON(x6JSON);
        botFlow.setBotJSON(botJSON);
        return flowMapper.updateById(botFlow) > 0;
    }

    @Override
    public List<BotClient> getClientList() {
        return flowMapper.clientList();
    }

    @Override
    public BotFlow getFlowInfo(Integer id) {
        return flowMapper.selectById(id);
    }

    @Override
    public boolean executeFlow(Integer id) {
        BotFlow flowInfo = this.getFlowInfo(id);
        BotClient botClient = flowMapper.getBotClientInfo(flowInfo.getClientId());
        if (flowInfo.getBotJSON() == null) {
            return false;
        }
        if (!(flowInfo.getStatus() == 1 && botClient.getStatus() == 2)) {
            return false;
        }
        JSONObject flow = new JSONObject();
        flow.fluentPut("type", "flow");
        flow.fluentPut("botJson", JSONObject.parseObject(flowInfo.getBotJSON()))
                .fluentPut("flowId", flowInfo.getId())
                .fluentPut("name", flowInfo.getFlowName());
        return clientFlowExecute.execute(flow, botClient.getClientId());
    }


    @Override
    public boolean disable(String id, Integer status) {
        BotFlow botClient = new BotFlow();
        botClient.setStatus(status);
        botClient.setId(Integer.parseInt(id));
        boolean stat = flowMapper.updateById(botClient) > 0;
        if (stat) {
            if (status == 1) {
                //启用
                quartzJob.addFlowJob(id);
            } else {
                quartzJob.deleteFlowJob(id);
            }
        }
        return stat;
    }

    @Override
    public void downloadFlow(HttpServletResponse response, String ids) {
        if (ids == null) {
            return;
        }

        QueryWrapper<BotFlow> wrapper = new QueryWrapper<>();
        wrapper.in("id", ids.split(","));
        List<Map<String, Object>> list = flowMapper.selectMaps(wrapper);
        if (list.isEmpty()) {
            return;
        }
        JSONArray array = new JSONArray(list);
        ServletUtils.downEncryptionFile(response, array, "bot-flow.bfg");
    }

    @Override
    public boolean uploadFlow(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        String extension = null;
        if (originalFilename != null) {
            extension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1).toLowerCase();
        }
        // 检查文件后缀名是否合法
        if (".bfg".equals(extension)) {
            return false;
        }
        try {
            byte[] bytes = file.getBytes();
            String decrypt = AESUtils.decrypt(bytes);
            JSONArray array = JSONArray.parseArray(decrypt);

            array.forEach(e -> {
                JSONObject _tmp = (JSONObject) e;
                BotFlow botFlow = new BotFlow();
                botFlow.setFlowName(_tmp.getString("flow_name"));
                botFlow.setFlowType(_tmp.getInteger("flow_type"));
                botFlow.setStatus(_tmp.getInteger("status"));
                botFlow.setCron(_tmp.getString("cron"));
                botFlow.setCreationDate(new Date());
                botFlow.setBotJSON(_tmp.getString("bot_json"));
                botFlow.setX6JSON(_tmp.getString("x6_json"));
                flowMapper.insert(botFlow);
            });
            return true;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
